#define _CRT_SECURE_NO_WARNINGS

#include <iostream>
#include <assert.h>
#include <vector>
using namespace std;

namespace my_vector
{
	template<class T>
	class vector
	{
	public:
		typedef T* iterator;
		typedef const T* const_iterator;

		vector()
			:_start(nullptr)
			, _finish(nullptr)
			, _endofstorage(nullptr)
		{}

		size_t size() const { return _finish - _start; }
		size_t capacity() const { return _endofstorage - _start; }
		size_t size() { return _finish - _start; }
		size_t capacity() { return _endofstorage - _start; }

		iterator begin() { return _start; }
		iterator end() { return _finish; }
		iterator begin() const { return _start; }
		iterator end() const { return _finish; }

		T& operator[](size_t pos) { return _start[pos]; }
		const T& operator[](size_t pos) const { return _start[pos]; }

		iterator& operator=(vector<T> v)
		{
			swap(v);
			return *this;
		}

		template<class InputIterator>
		vector(InputIterator first, InputIterator last)
			:_start(nullptr)
			, _finish(nullptr)
			, _endofstorage(nullptr)
		{
			while (first != last)
			{
				push_back(*first++);
			}
		}

		vector(const vector<T>& v)
			:_start(nullptr)
			, _finish(nullptr)
			, _endofstorage(nullptr)
		{
			vector<T> tmp(v.begin(), v.end());
			swap(tmp);
		}

		void swap(vector<T>& v)
		{
			std::swap(_start, v._start);
			std::swap(_finish, v._finish);
			std::swap(_endofstorage, v._endofstorage);
		}

		void reserve(size_t n)
		{
			if (n > capacity())
			{
				size_t oldsize = size();
				iterator tmp = new T[n];

				if (_start)
				{
					//memcpy(tmp, _start, sizeof(T) * oldsize);

					for (size_t i = 0; i < oldsize; i++) tmp[i] = _start[i];

					delete[] _start;
				}

				_start = tmp;
				_finish = _start + oldsize;
				_endofstorage = _start + n;
			}
		}

		void resize(size_t n, T& val = T())
		{
			if (n > capacity()) reserve(n);
			if (n > size())
			{
				while (_finish < _start + n)
				{
					*_finish = val;
					++_finish;
				}
			}
			else _finish = _start + n;
		}

		bool empty() { return _start == _finish; }

		void push_back(const T& val)
		{
			if (_finish == _endofstorage)
			{
				size_t newcapacity = capacity() == 0 ? 4 : capacity() * 2;
				reserve(newcapacity);
			}

			*_finish = val;
			_finish++;
		}

		void pop_back() { assert(!empty());  _finish--; }

		iterator insert(iterator pos, const T& val)
		{
			assert(pos >= _start && pos < _finish);

			if (_finish == _endofstorage)
			{
				size_t possize = pos - _start;
				size_t newcapacity = capacity() == 0 ? 4 : capacity() * 2;
				reserve(newcapacity);
				pos = _start + possize;
			}

			iterator tmp = _finish;
			while (tmp > pos)
			{
				*tmp = *(tmp - 1);
				tmp--;
			}
			*pos = val;
			_finish++;

			return pos;
		}

		iterator erase(iterator pos)
		{
			assert(pos >= _start && pos < _finish);

			iterator tmp = pos + 1;
			while (tmp != _finish)
			{
				*(tmp - 1) = *tmp; 
				tmp++;
			}
			_finish--;
			return pos;
		}

		void print()
		{
			for (size_t i = 0; i < size(); i++) cout << _start[i] << ' ';
			cout << endl;
		}

		void print() const 
		{
			for (size_t i = 0; i < size(); i++) cout << _start[i] << ' ';
			cout << endl;
		}

		void clear() { _finish = _start; }

		T& back() { assert(!empty()); return _start[size() - 1]; }

	private:
		iterator _start;
		iterator _finish;
		iterator _endofstorage;
	};

	void test()
	{
		vector<int> v;
		v.push_back(1);
		v.push_back(2);
		v.push_back(3);
		v.push_back(4);
		v.push_back(5);
		v.push_back(6);

		v.print();

		vector<int>::iterator it = v.insert(find(v.begin(), v.end(), 3), 999);
		it = v.insert(it, 666);
		it = v.insert(it, 777);
		it = v.insert(it, 888);

		v.print();

		it = v.erase(it);
		it = v.erase(it);
		it = v.erase(it);
		it = v.erase(it);

		v.print();

		v.pop_back();
		v.pop_back();
		v.pop_back();

		v.print();

		vector<int> v1(v);
		v1.print();
		vector<int> v2 = v;
		v2.print();

		cout << v2.back() << endl;
		v2.back() = 999;
		cout << v2.back();
	}
}